package com.duojuhe.coremodule.chat.im.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.duojuhe.cache.SystemDictCache;
import com.duojuhe.common.constant.DataScopeConstants;
import com.duojuhe.coremodule.chat.im.entity.*;
import com.duojuhe.coremodule.chat.im.handle.ChatBuildMessageUtils;
import com.duojuhe.coremodule.chat.im.handle.ChatHandleCommonKit;
import com.duojuhe.coremodule.chat.im.mapper.*;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.*;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.notice.*;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.user.QueryChatGroupUserPageReq;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.user.QueryChatGroupUserPageRes;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.user.QueryInviteChatGroupUserPageReq;
import com.duojuhe.coremodule.chat.im.pojo.dto.chatgroup.user.QueryInviteChatGroupUserPageRes;
import com.duojuhe.coremodule.chat.im.pojo.dto.talkrecord.sendtalk.SendTalkReq;
import com.duojuhe.coremodule.chat.im.service.ChatGroupService;
import com.duojuhe.websocket.subscriber.message.talk.MessageBodyRes;
import com.duojuhe.websocket.subscriber.message.talk.bean.invite.ChatUserRes;
import com.duojuhe.common.annotation.DataScopeFilter;
import com.duojuhe.common.annotation.KeyLock;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.constant.SingleStringConstant;
import com.duojuhe.common.constant.SystemConstants;
import com.duojuhe.common.enums.chat.ImChatEnum;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.redis.redisson.RedisSonLockUtils;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.PageResult;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.encryption.md5.MD5Util;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.system.entity.SystemDict;
import com.duojuhe.coremodule.system.entity.SystemUser;
import com.duojuhe.coremodule.system.mapper.SystemUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ChatGroupServiceImpl extends BaseService implements ChatGroupService {
    @Resource
    private ChatHandleCommonKit chatHandleCommonKit;
    @Resource
    private SystemDictCache systemDictCache;
    @Resource
    private ChatGroupUserMapper chatGroupUserMapper;
    @Resource
    private ChatGroupMapper chatGroupMapper;
    @Resource
    private SystemUserMapper systemUserMapper;
    @Resource
    private ChatGroupNoticeMapper chatGroupNoticeMapper;
    @Resource
    private ChatUsersChatListMapper chatUsersChatListMapper;
    @Resource
    private ChatTalkRecordMapper chatTalkRecordMapper;
    @Resource
    private ChatTalkRecordInviteMapper chatTalkRecordInviteMapper;

    /**
     * 分页查询用户群组 用户群聊服务接口
     * @param req
     * @return
     */
    @DataScopeFilter(userId = "t.user_id",dataScope = DataScopeConstants.SELF_DATA)
    @Override
    public ServiceResult<PageResult<List<QueryMyChatGroupPageRes>>> queryMyChatGroupPageResList(QueryMyChatGroupPageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "createTime desc, groupId desc");
        List<QueryMyChatGroupPageRes> list = chatGroupMapper.queryMyChatGroupPageResList(req);
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 根据id获取群详情 获取群信息服务接口
     * @param req
     * @return
     */
    @Override
    public ServiceResult<QueryChatGroupRes> queryChatGroupResByGroupId(ChatGroupIdReq req) {
        String groupId = req.getGroupId();
        QueryChatGroupRes groupRes = chatGroupMapper.queryChatGroupResByGroupId(groupId);
        if (groupRes==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        String userId = getCurrentLoginUserId();
        //主键ID 当前用户id和群组id的MD5值
        String id = MD5Util.getMD532(userId+groupRes.getGroupId());
        //查询群组用户表
        ChatGroupUser groupUser = chatGroupUserMapper.selectByPrimaryKey(id);
        groupRes.setVisitCard(groupUser!=null?groupUser.getVisitCard():"");
        //查询会话记录表
        ChatUsersChatList chatList = chatUsersChatListMapper.selectByPrimaryKey(id);
        groupRes.setIsDisturb(chatList!=null?chatList.getIsDisturb():ImChatEnum.IM_YES_NO.YES.getKey());
        groupRes.setIsManager(userId.equals(groupRes.getCreateUserId()));
        //查询第一条公告最新的
        PageHelperUtil.defaultOrderBy("sort desc,createTime desc,noticeId desc");
        PageHelperUtil.defaultStartPage(0,1);
        QueryChatGroupNoticePageRes noticePageRes = chatGroupNoticeMapper.queryChatGroupNoticePageResListByGroupId(groupId).stream().findFirst().orElse(new QueryChatGroupNoticePageRes());
        if (StringUtils.isNotBlank(noticePageRes.getGroupId())){
            ChatGroupNoticeRes groupNoticeRes = new ChatGroupNoticeRes();
            groupNoticeRes.setTitle(noticePageRes.getNoticeTitle());
            groupNoticeRes.setContent(noticePageRes.getContent());
            groupRes.setGroupNoticeRes(groupNoticeRes);
        }
        return ServiceResult.ok(groupRes);
    }

    /**
     * 创建群组
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult saveChatGroup(SaveChatGroupReq req) {
        //校验用户id集合的合法有效性并返回map集合
        Map<String, SystemUser> systemUserMap = buildSystemUserMapByUserIdList(req.getUserIdList());
        //群组id
        String groupId = UUIDUtils.getUUID32();
        //入群通知类型
        Integer inviteType = ImChatEnum.InviteType.JOIN_GROUP_NOTICE.getKey();
        RLock lock = null;
        try {
            lock = RedisSonLockUtils.fairLock(groupId);
            //当前登录人
            UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
            //当前时间
            Date nowDate = new Date();
            //否标识
            Integer no = ImChatEnum.IM_YES_NO.NO.getKey();
            //当前用户id
            String userId = userTokenInfoVo.getUserId();
            //创建群组
            ChatGroup chatGroup = new ChatGroup();
            chatGroup.setGroupId(groupId);
            chatGroup.setGroupAvatar(req.getGroupAvatar());
            chatGroup.setGroupIntroduce(req.getGroupIntroduce());
            chatGroup.setGroupName(req.getGroupName());
            chatGroup.setUpdateTime(nowDate);
            chatGroup.setUpdateTime(nowDate);
            chatGroup.setCreateUserId(userId);
            chatGroup.setCreateTime(nowDate);
            chatGroup.setUpdateUserId(userId);
            chatGroup.setCreateDeptId(userTokenInfoVo.getCreateDeptId());
            chatGroup.setTenantId(userTokenInfoVo.getTenantId());
            chatGroup.setMaxPeopleNumber(SystemConstants.GROUP_MAX_PEOPLE_NUMBER);
            chatGroup.setIsOvert(ImChatEnum.IM_YES_NO.YES.getKey());
            chatGroup.setIsDismiss(no);
            chatGroup.setIsMute(no);
            //构建群成员表
            List<ChatGroupUser> chatGroupUserList = new ArrayList<>();
            //群组用户id集合
            List<String> userIdList = req.getUserIdList();
            userIdList.add(userId);
            //构建群成员聊天会话
            List<ChatUsersChatList> chatUsersChatListList = new ArrayList<>();
            for (String uid: req.getUserIdList()){
                SystemUser systemUser = systemUserMap.get(uid);
                if (!uid.equals(userId)&&systemUser==null){
                    continue;
                }
                //主键ID 当前用户id和群组id的MD5值
                String id = MD5Util.getMD532(uid+groupId);
                //构建群成员表
                ChatGroupUser chatGroupUser = new ChatGroupUser();
                chatGroupUser.setId(id);
                chatGroupUser.setGroupId(groupId);
                chatGroupUser.setUserId(uid);
                chatGroupUser.setLeader(uid.equals(userId)?ImChatEnum.GroupUser.LEADER.getKey():ImChatEnum.GroupUser.MEMBER.getKey());
                chatGroupUser.setIsQuit(no);
                chatGroupUser.setIsMute(no);
                chatGroupUser.setJoinGroupTime(nowDate);
                chatGroupUserList.add(chatGroupUser);
                //构建新的聊天会话
                ChatUsersChatList chatUsersChatList = new ChatUsersChatList();
                chatUsersChatList.setId(id);
                chatUsersChatList.setTalkType(ImChatEnum.TalkType.GROUP_CHAT.getKey());
                chatUsersChatList.setUserId(uid);
                chatUsersChatList.setCreateUserId(uid);
                chatUsersChatList.setReceiverId(groupId);
                chatUsersChatList.setCreateTime(nowDate);
                chatUsersChatList.setUpdateTime(nowDate);
                chatUsersChatList.setLastReleaseTime(nowDate);
                chatUsersChatList.setUnreadNum(0);
                chatUsersChatList.setSort(0);
                chatUsersChatList.setIsDelete(no);
                chatUsersChatList.setDeleteTime(nowDate);
                chatUsersChatList.setIsDisturb(no);
                chatUsersChatList.setIsTop(no);
                chatUsersChatList.setIsRobot(no);
                chatUsersChatListList.add(chatUsersChatList);
            }
            //插入群组
            chatGroupMapper.insertSelective(chatGroup);
            //插入群成员表
            chatGroupUserMapper.batchInsertListUseAllCols(chatGroupUserList);
            //插入会话
            chatUsersChatListMapper.batchInsertListUseAllCols(chatUsersChatListList);
            //发送消息
            return ServiceResult.ok(groupId);
        }catch (Exception e){
            throw new DuoJuHeException("创建群组失败!");
        }finally {
            RedisSonLockUtils.unlock(lock);
        }
    }

    /**
     * 修改群组
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "groupId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult updateChatGroup(UpdateChatGroupReq req) {
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(req.getGroupId());
        if (group==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前时间
        Date nowDate = new Date();
        ChatGroup chatGroup = new ChatGroup();
        chatGroup.setGroupId(req.getGroupId());
        chatGroup.setGroupAvatar(req.getGroupAvatar());
        chatGroup.setGroupIntroduce(req.getGroupIntroduce());
        chatGroup.setGroupName(req.getGroupName());
        chatGroup.setUpdateTime(nowDate);
        chatGroup.setUpdateUserId(userTokenInfoVo.getUserId());
        chatGroupMapper.updateByPrimaryKeySelective(chatGroup);

        //发送消息
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }


    /**
     * 邀请好友入群组 邀请好友加入群聊服务接口
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "groupId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult inviteJoinChatGroup(InviteJoinChatGroupReq req) {
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(req.getGroupId());
        if (group==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //校验用户id集合的合法有效性并返回map集合
        Map<String, SystemUser> systemUserMap = buildSystemUserMapByUserIdList(req.getUserIdList());
        //邀请人数总和
        int inviteNum = req.getUserIdList().size();
        List<ChatGroupUser> chatGroupUserList = chatGroupUserMapper.queryChatGroupUserListByGroupId(req.getGroupId());
        //还可邀请人数
        int memberNum = chatGroupUserList.size()+inviteNum-SystemConstants.GROUP_MAX_PEOPLE_NUMBER;
        if (memberNum>0){
            return ServiceResult.fail("超过群组最大人数限制，只可邀请"+(inviteNum-memberNum)+"人");
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前用户id
        String userId = userTokenInfoVo.getUserId();
        //查询发送者信息
        SystemUser currentSystemUser = systemUserMapper.selectByPrimaryKey(userId);
        if (currentSystemUser==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //群组id
        String groupId = req.getGroupId();
        //当前时间
        Date nowDate = new Date();
        //否标识
        Integer no = ImChatEnum.IM_YES_NO.NO.getKey();
        //主键ID 当前用户id和群组id的MD5值
        String groupUserId = MD5Util.getMD532(userId+groupId);
        ChatGroupUser groupUser = chatGroupUserMapper.selectByPrimaryKey(groupUserId);
        if (groupUser==null){
            return ServiceResult.fail("暂不属于群组成员，无法邀请好友入群组！");
        }
        //被处理用户对象集合
        List<ChatUserRes> chatUserResList = new ArrayList<>();
        //构建群成员表 构建新的聊天会话
        for (String uid: req.getUserIdList()){
            if (userId.equals(uid)){
                //群主是不可被移除的
                continue;
            }
            SystemUser systemUser = systemUserMap.get(uid);
            if (systemUser==null){
                continue;
            }
            //被处理用户集合
            chatUserResList.add(new ChatUserRes(systemUser));
            //主键ID 当前用户id和群组id的MD5值
            String id = MD5Util.getMD532(uid+groupId);
            //构建群成员表
            ChatGroupUser chatGroupUser = new ChatGroupUser();
            chatGroupUser.setId(id);
            chatGroupUser.setGroupId(groupId);
            chatGroupUser.setUserId(uid);
            chatGroupUser.setIsQuit(no);
            chatGroupUser.setIsMute(no);
            chatGroupUser.setJoinGroupTime(nowDate);
            chatGroupUser.setLeader(ImChatEnum.GroupUser.MEMBER.getKey());
            ChatGroupUser chatUser = chatGroupUserMapper.selectByPrimaryKey(id);
            if (chatUser==null){
                chatGroupUserMapper.insertSelective(chatGroupUser);
            }else {
                chatGroupUserMapper.updateByPrimaryKeySelective(chatGroupUser);
            }
            //构建新的聊天会话
            ChatUsersChatList chatUsersChatList = new ChatUsersChatList();
            chatUsersChatList.setId(id);
            chatUsersChatList.setTalkType(ImChatEnum.TalkType.GROUP_CHAT.getKey());
            chatUsersChatList.setUserId(uid);
            chatUsersChatList.setCreateUserId(uid);
            chatUsersChatList.setReceiverId(groupId);
            chatUsersChatList.setCreateTime(nowDate);
            chatUsersChatList.setUpdateTime(nowDate);
            chatUsersChatList.setLastReleaseTime(nowDate);
            chatUsersChatList.setUnreadNum(0);
            chatUsersChatList.setSort(0);
            chatUsersChatList.setIsDelete(no);
            chatUsersChatList.setDeleteTime(nowDate);
            chatUsersChatList.setIsDisturb(no);
            chatUsersChatList.setIsTop(no);
            chatUsersChatList.setIsRobot(no);
            ChatUsersChatList chatList = chatUsersChatListMapper.selectByPrimaryKey(id);
            if (chatList==null){
                chatUsersChatListMapper.insertSelective(chatUsersChatList);
            }else {
                chatUsersChatListMapper.updateByPrimaryKeySelective(chatUsersChatList);
            }
        }
        //构建消息记录表
        //入群通知类型
        Integer inviteType = ImChatEnum.InviteType.JOIN_GROUP_NOTICE.getKey();
        handleGroupNoticeMessage(inviteType,chatUserResList,currentSystemUser,group);
        //发送消息
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }


    /**
     * 移除群组 移除群聊成员服务接口
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "groupId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult removeChatGroupUser(RemoveChatGroupUserReq req) {
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(req.getGroupId());
        if (group==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //校验用户id集合的合法有效性并返回map集合
        Map<String, SystemUser> systemUserMap = buildSystemUserMapByUserIdList(req.getUserIdList());
        //查询发送者信息
        SystemUser currentSystemUser = systemUserMapper.selectByPrimaryKey(getCurrentLoginUserId());
        if (currentSystemUser==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //被处理用户对象集合
        List<ChatUserRes> chatUserResList = new ArrayList<>();
        //当前时间
        Date nowDate = new Date();
        //分组id
        String groupId = group.getGroupId();
        for (String uId:req.getUserIdList()){
            if (uId.equals(group.getCreateUserId())){
                //群主是不可被移除的
                continue;
            }
            SystemUser systemUser = systemUserMap.get(uId);
            if (systemUser==null){
                continue;
            }
            //被处理用户集合
            chatUserResList.add(new ChatUserRes(systemUser));

            //主键ID 当前用户id和群组id的MD5值
            String id = MD5Util.getMD532(uId+groupId);
            //群组用户
            ChatGroupUser chatGroupUser = new ChatGroupUser();
            chatGroupUser.setId(id);
            chatGroupUser.setIsQuit(ImChatEnum.IM_YES_NO.YES.getKey());
            chatGroupUser.setQuitGroupTime(nowDate);
            //会话列表
            ChatUsersChatList chatList = new ChatUsersChatList();
            chatList.setId(id);
            chatList.setIsDelete(ImChatEnum.IM_YES_NO.YES.getKey());
            chatList.setUnreadNum(0);
            chatList.setDeleteTime(nowDate);
            //更新用户会话列表
            chatUsersChatListMapper.updateByPrimaryKeySelective(chatList);
            //更新群组用户
            chatGroupUserMapper.updateByPrimaryKeySelective(chatGroupUser);
        }
        //插入消息记录
        //入群通知类型
        Integer inviteType = ImChatEnum.InviteType.KICK_OUT_GROUP_NOTICE.getKey();
        handleGroupNoticeMessage(inviteType,chatUserResList,currentSystemUser,group);
        //发送消息
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 解散群组 管理员解散群聊服务接口
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @KeyLock(lockKeyParts = "groupId")
    @Override
    public ServiceResult dismissChatGroupByGroupId(ChatGroupIdReq req) {
        String groupId = req.getGroupId();
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(groupId);
        //yes标识
        Integer yes = ImChatEnum.IM_YES_NO.YES.getKey();
        if (group==null || yes.equals(group.getIsDismiss())){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        if (!userTokenInfoVo.getUserId().equals(group.getCreateUserId())){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前时间
        Date nowDate = new Date();
        //更新群组
        ChatGroup chatGroup = new ChatGroup();
        chatGroup.setGroupId(groupId);
        chatGroup.setIsDismiss(yes);
        chatGroup.setDismissedTime(nowDate);
        chatGroupMapper.updateByPrimaryKeySelective(chatGroup);
        List<ChatGroupUser> chatGroupUserList = chatGroupUserMapper.queryChatGroupUserListByGroupId(groupId);
        for (ChatGroupUser groupUser:chatGroupUserList){
            //主键ID 当前用户id和接收id的MD5值
            String id = MD5Util.getMD532(groupUser.getUserId()+groupId);
            ChatUsersChatList chatUsersChatList = new ChatUsersChatList();
            chatUsersChatList.setId(id);
            chatUsersChatList.setIsDelete(yes);
            chatUsersChatList.setLastMessage("");
            chatUsersChatList.setUnreadNum(0);
            chatUsersChatList.setLastReleaseTime(nowDate);
            //群组用户
            ChatGroupUser chatGroupUser = new ChatGroupUser();
            chatGroupUser.setId(groupUser.getId());
            chatGroupUser.setIsQuit(yes);
            chatGroupUser.setQuitGroupTime(nowDate);
            //更新群组用户
            chatGroupUserMapper.updateByPrimaryKeySelective(chatGroupUser);
            //更新聊天会话
            chatUsersChatListMapper.updateByPrimaryKeySelective(chatUsersChatList);
        }
        //发送消息预留

        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 退出群组
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @KeyLock(lockKeyParts = "groupId")
    @Override
    public ServiceResult secedeChatGroupByGroupId(ChatGroupIdReq req) {
        String groupId = req.getGroupId();
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(groupId);
        if (group==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        if (userTokenInfoVo.getUserId().equals(group.getCreateUserId())){
            return ServiceResult.fail("你是群主不可退出!");
        }
        //查询发送者信息
        SystemUser currentSystemUser = systemUserMapper.selectByPrimaryKey(userTokenInfoVo.getUserId());
        if (currentSystemUser==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前时间
        Date nowDate = new Date();
        //主键ID 当前用户id和群组id的MD5值
        String id = MD5Util.getMD532(userTokenInfoVo.getUserId()+groupId);
        ChatGroupUser chatGroupUser = new ChatGroupUser();
        chatGroupUser.setId(id);
        chatGroupUser.setIsQuit(ImChatEnum.IM_YES_NO.YES.getKey());
        chatGroupUser.setQuitGroupTime(nowDate);
        chatGroupUserMapper.updateByPrimaryKeySelective(chatGroupUser);
        //删除会话记录表
        ChatUsersChatList chatUsersChatList = new ChatUsersChatList();
        chatUsersChatList.setId(id);
        chatUsersChatList.setIsDelete(ImChatEnum.IM_YES_NO.YES.getKey());
        chatUsersChatList.setDeleteTime(nowDate);
        chatUsersChatListMapper.updateByPrimaryKeySelective(chatUsersChatList);
        //插入消息记录
        //被处理用户对象集合
        List<ChatUserRes> chatUserResList = new ArrayList<>();
        chatUserResList.add(new ChatUserRes(currentSystemUser));
        //入群通知类型
        Integer inviteType = ImChatEnum.InviteType.QUIT_GROUP_NOTICE.getKey();
        handleGroupNoticeMessage(inviteType,chatUserResList,currentSystemUser,group);
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 设置群组全员禁言
     * @param req
     * @return
     */
    @Override
    public ServiceResult setMuteChatGroup(SetMuteChatGroupReq req) {
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(req.getGroupId());
        if (group==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        if (!userTokenInfoVo.getUserId().equals(group.getCreateUserId())){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        if (!group.getIsMute().equals(req.getIsMute())){
            ChatGroup chatGroup = new ChatGroup();
            chatGroup.setGroupId(group.getGroupId());
            chatGroup.setIsMute(req.getIsMute());
            chatGroupMapper.updateByPrimaryKeySelective(chatGroup);
        }
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 修改群聊名片服务接口
     * @param req
     * @return
     */
    @Override
    public ServiceResult updateUserChatGroupVisitCard(UpdateUserChatGroupVisitCardReq req) {
        //查询用户是否在群组内
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //主键ID 当前用户id和群组id的MD5值
        String id = MD5Util.getMD532(userTokenInfoVo.getUserId()+req.getGroupId());
        ChatGroupUser groupUser = chatGroupUserMapper.selectByPrimaryKey(id);
        if (groupUser==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        ChatGroupUser chatGroupUser = new ChatGroupUser();
        chatGroupUser.setId(id);
        chatGroupUser.setVisitCard(req.getVisitCard());
        chatGroupUserMapper.updateByPrimaryKeySelective(chatGroupUser);
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 分页查询群组公告 获取群组公告列表
     * @param req
     * @return
     */
    @Override
    public ServiceResult<PageResult<List<QueryChatGroupNoticePageRes>>> queryChatGroupNoticePageResList(QueryChatGroupNoticePageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "createTime desc, groupId desc");
        List<QueryChatGroupNoticePageRes> list = chatGroupNoticeMapper.queryChatGroupNoticePageResListByGroupId(req.getGroupId());
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 保存群公告
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult saveChatGroupNotice(SaveChatGroupNoticeReq req) {
        ChatGroup group = chatGroupMapper.selectByPrimaryKey(req.getGroupId());
        if (group==null){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前时间
        Date nowDate = new Date();
        ChatGroupNotice chatGroupNotice = new ChatGroupNotice();
        chatGroupNotice.setNoticeId(UUIDUtils.getUUID32());
        chatGroupNotice.setNoticeTitle(req.getNoticeTitle());
        chatGroupNotice.setContent(req.getContent());
        chatGroupNotice.setCreateTime(nowDate);
        chatGroupNotice.setUpdateTime(nowDate);
        chatGroupNotice.setSort(0);
        chatGroupNotice.setGroupId(req.getGroupId());
        chatGroupNotice.setCreateUserId(userTokenInfoVo.getUserId());
        chatGroupNoticeMapper.insertSelective(chatGroupNotice);
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 修改群公告
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult updateChatGroupNotice(UpdateChatGroupNoticeReq req) {
        ChatGroupNotice groupNotice = chatGroupNoticeMapper.selectByPrimaryKey(req.getNoticeId());
        if (groupNotice==null || !req.getGroupId().equals(groupNotice.getGroupId())){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        ChatGroupNotice chatGroupNotice = new ChatGroupNotice();
        chatGroupNotice.setNoticeId(req.getNoticeId());
        chatGroupNotice.setNoticeTitle(req.getNoticeTitle());
        chatGroupNotice.setContent(req.getContent());
        chatGroupNotice.setUpdateTime(new Date());
        chatGroupNoticeMapper.updateByPrimaryKeySelective(chatGroupNotice);
        return ServiceResult.ok(ErrorCodes.SUCCESS);
    }

    /**
     * 分页查询群成员列表 获取群组成员列表
     * @param req
     * @return
     */
    @Override
    public ServiceResult<PageResult<List<QueryChatGroupUserPageRes>>> queryChatGroupUserPageResList(QueryChatGroupUserPageReq req) {
        PageHelperUtil.orderByAndStartPage(req, "joinGroupTime desc, id desc");
        List<QueryChatGroupUserPageRes> list = chatGroupUserMapper.queryChatGroupUserPageResListByGroupId(req.getGroupId());
        for (QueryChatGroupUserPageRes res:list){
            SystemDict gender = systemDictCache.getSystemDictByDictCode(res.getGenderCode());
            res.setGenderName(gender.getDictName());
        }
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 分页查询获取用户可邀请加入群组的好友列表 获取用户可邀请加入群组的好友列表
     * @param req
     * @return
     */
    @DataScopeFilter(dataScope = DataScopeConstants.SELF_DATA)
    @Override
    public ServiceResult<PageResult<List<QueryInviteChatGroupUserPageRes>>> queryInviteChatGroupUserPageResList(QueryInviteChatGroupUserPageReq req) {
        //查询用户是否在群组内
        if (StringUtils.isNotBlank(req.getGroupId())){
            //当前登录人
            UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
            //主键ID 当前用户id和群组id的MD5值
            String id = MD5Util.getMD532(userTokenInfoVo.getUserId()+req.getGroupId());
            ChatGroupUser groupUser = chatGroupUserMapper.selectByPrimaryKey(id);
            if (groupUser==null){
                return PageHelperUtil.returnServiceResult(req,new ArrayList<>());
            }
        }
        PageHelperUtil.orderByAndStartPage(req, "createTime desc, id desc");
        List<QueryInviteChatGroupUserPageRes> list = chatGroupUserMapper.queryInviteChatGroupUserPageResList(req);
        for (QueryInviteChatGroupUserPageRes res:list){
            SystemDict gender = systemDictCache.getSystemDictByDictCode(res.getGenderCode());
            res.setGenderName(gender.getDictName());
        }
        return PageHelperUtil.returnServiceResult(req,list);
    }


    /**
     * 校验用户id集合是否合法有效
     * @param userIdList
     */
    private  Map<String, SystemUser> buildSystemUserMapByUserIdList(List<String> userIdList){
        if (userIdList==null||userIdList.isEmpty()){
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        List<SystemUser> systemUserList = systemUserMapper.querySystemUserListByUserIdList(userIdList);
        if (userIdList.size()!=systemUserList.size()){
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        return systemUserList.stream().collect(Collectors.toMap(SystemUser::getUserId, e -> e));
    }


    /**
     * 处理群组通知
     * @param systemUser
     * @param chatGroup
     */
    private void handleGroupNoticeMessage(Integer inviteType,List<ChatUserRes> chatUserResList,SystemUser systemUser,ChatGroup chatGroup){
        //被处理用户id集合
        List<String> userIds = chatUserResList.stream().map(ChatUserRes::getUserId).collect(Collectors.toList());
        //消息类型
        Integer msgType = ImChatEnum.TalkMessageType.GROUP_INVITE_MESSAGE.getKey();
        SendTalkReq sendTalk = new SendTalkReq();
        sendTalk.setTalkType(ImChatEnum.TalkType.GROUP_CHAT.getKey());
        sendTalk.setReceiverId(chatGroup.getGroupId());
        ChatTalkRecord record = chatHandleCommonKit.buildGroupNoticeChatTalkRecord(msgType,sendTalk,systemUser,chatGroup);
        //当前用户消息快照
        String operateUserSnapshot = JSONObject.toJSONString(new ChatUserRes(systemUser));
        //构建入群通知信息表
        ChatTalkRecordInvite talkRecordInvite = new ChatTalkRecordInvite();
        talkRecordInvite.setId(record.getRecordId());
        talkRecordInvite.setInviteType(inviteType);
        talkRecordInvite.setRecordId(record.getRecordId());
        talkRecordInvite.setCreateTime(record.getCreateTime());
        talkRecordInvite.setCreateUserId(record.getCreateUserId());
        talkRecordInvite.setOperateUserId(record.getUserId());
        talkRecordInvite.setOperateUserSnapshot(operateUserSnapshot);
        talkRecordInvite.setUserIds(StringUtils.join(userIds, SingleStringConstant.COMMA));
        talkRecordInvite.setUserSnapshot(JSON.toJSONString(chatUserResList));
        //插入群消息
        chatTalkRecordMapper.insertSelective(record);
        //插入消息关联的通知消息
        chatTalkRecordInviteMapper.insertSelective(talkRecordInvite);
        //构建发送消息
        MessageBodyRes bodyRes = ChatBuildMessageUtils.buildMessageBodyRes(record);
        bodyRes.setInvite(ChatBuildMessageUtils.buildRecordInviteToInviteRes(talkRecordInvite));
        //保存最后的消息记录
        chatHandleCommonKit.handleLastMessage(record);
        //发送消息到各个订阅端
        chatHandleCommonKit.handleSendChatSubscribe(bodyRes);
    }




}
